/*
 * StrLib.c
 * VB Script Analyzer
 * @author Gregoire JACOB (gregoire.jacob@orange-ftgroup.com)
 * @date 21/01/2008
 * @version 1.0
 * Basic functions on character and strings to analyze a file.
 */

#include ".\Includes\Analyzer.h"

char parseString(FILE * script, char * str){
	int i = 0;	//position in str
	char c = 0;

	while(1){
		c = fgetc(script);
		if (c == ' ') continue;	//skipping spaces
		if (c == '(' || c == ',' || c == ')'
			|| c == '\n' || c == '\r') break;
		str[i] = c;
		i++;
	}
	str[i] = '\0';	//string must be null-terminated
	return c;
}

int decomposeLine(char * line, char * tokens, int lines, int columns){
	int i = 0;	//position in line
	int j = 0;	//line index in the table of tokens
	int k = 0;	//index of a character in a line
	char c = 0;

	for(i=0;i<=strlen(line);i++){
		c = line[i];
		if (c == ' '|| c == ','|| c == '('|| c == ')'|| 
			c == '.' || c=='\t' || c== 0 || c == 10 || c == 13){
			if(k>0){//non empty token
				tokens[(j*columns)+k] = '\0';	//previous name must be null terminated
				j++;							//next line
				k=0;							//new clear line
				continue;
			}
			continue;
		}
		if (c == '"'){//Cas d'une chaine
			int start = i;
			int closed = 0;
			tokens[(j*columns)+k] = '"';
			while(!closed){
				i++; 
				if(k<columns){//string too long (cut)
					k++;
				}else{
					tokens[(j*columns)+k-2] = '"';
					tokens[(j*columns)+k-1] = '\0';
				}
				c = line[i];
				tokens[(j*columns)+k] = c;
				if(c=='"') closed= 1;
				if(c==0){//unclosed string
					int blank;
					for(blank=1;blank<columns;blank++){
						//First blank close the token
						if(tokens[(j*columns)+blank]== ' '){break;}
						if(tokens[(j*columns)+blank]== 0){
							tokens[(j*columns)+blank-1] = '"';
							tokens[(j*columns)+blank] = '\0';
							return j+1;
						}
					}
					i=start+blank; k = blank;
					tokens[(j*columns)+blank] = '"';
					closed = 1;
				}
			}//while
			tokens[(j*columns)+k+1] = '\0';
			j++;
			k=0;
			continue;
		}
		if (c == '='){
			if(k>0){//non empty token
				tokens[(j*columns)+k] = '\0';	//previous name must be null terminated
				j++;
			}
			if(j>=lines) break;
			tokens[(j*columns)] = '=';// = as a new token
			tokens[(j*columns)+1] = '\0';
			j++;
			k=0; //new clear line
			continue;
		}

		if (c == '&'){
			if(k>0){//non empty token
				tokens[(j*columns)+k] = '\0';	//previous name must be null terminated
				j++;
			}
			if(j>=lines) break;
			tokens[(j*columns)] = '&';// & as a new token
			tokens[(j*columns)+1] = '\0';
			j++;
			k=0; //new clear line
			continue;
		}

		if (c == '\n' || c == '\r'){
			if(k>0){//non empty token
				tokens[(j*columns)+k] = '\0';	//previous name must be null terminated
				j++;							//next lines
				break;
			}
		}
		//If maximum of tokens has already been parsed
		if(j>=lines) break;
		
		if(line[i] != ' '){
			tokens[(j*columns)+k] = line[i]; k++;
		}
	}//for
	return j;
}

void fgetAlignedLine(char * line,int length, FILE * file){
	char c;
	do{//skip blanks
		c=fgetc(file);
	}while(c==' '||c=='\t');
	if(feof(file)) return;
	fseek(file,-1,SEEK_CUR);
	fgets(line,length,file);
}

int strcasecmp(const char *s1, const char *s2){
	while (*s1 != '\0' && tolower(*s1) == tolower(*s2)){
		s1++;
		s2++;
    }
	return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
}


void normalizeLine(struct LINE * line){
	char lineout[LINE_LENGTH];
	char character[4] = "\"X\"";
	char * str1, * str2, * chrloc = NULL;
	int code, nb, i, j, paropen, parclose, len, nonempty = 0;

	lineout[0] = 0;
	str1 = &(line->line[0]);
	//Evaluating chr
	while(chrloc = strcasestr(str1,"chr(")){
		*chrloc = 0;
		strcat_s(lineout,LINE_LENGTH,str1);
		str1 = chrloc+4;
		nb = sscanf_s(str1,"%d",&code);
		character[1] = getCharacter(code);
		strcat_s(lineout,LINE_LENGTH,character);
		//Positioning on next element
		while(*str1 != ' ' && *str1 != '&' && *str1 != 0){
			str1++;
		}
	}
	strcat_s(lineout,LINE_LENGTH,str1);
	len = (int)strlen(lineout);
	if(lineout[len-1]!='\n'){
		lineout[len]='\n';
		lineout[len+1]=0;
	}
	//Remove tabulation
	for(i=0;i<len;i++){
		if(lineout[i]=='\t') lineout[i]=' ';
	}
	//Remove duplicated blanks and "
	for(i=0,j=0;i<len;i++){
		lineout[j] = lineout[i];
		j++;
		if(lineout[i]==' '&&lineout[i+1]==' '){i++;}
		if(lineout[i]=='\"'){
			if(lineout[i+1]=='\"'){
				if(i<len-2){
					while(lineout[i+2]=='\"'){i++;}
					if(lineout[i+2]!=' '){i++;continue;}
				}
			}
		}
	} lineout[j]=0;
	//Concatenate strings 
	str1 = &(line->line[0]);
	*str1 = 0;
	str2 = &(lineout[0]);
	for(i=0,j=0;i<LINE_LENGTH;i++,j++){
		if(lineout[i]=='&'||lineout[i]=='+'){
			strcpy(str1,str2);  
			//Test for consecutive string
			paropen = 0;
			if(lineout[i-1]=='"') paropen=2;
			if(lineout[i-2]=='"') paropen=3;
			if(lineout[i-3]=='"') paropen=4;
			parclose = 0;
			if(i<LINE_LENGTH-1 && lineout[i+1]=='"') parclose=1;
			if(i<LINE_LENGTH-2 && lineout[i+2]=='"') parclose=2;
			if(i<LINE_LENGTH-3 && lineout[i+3]=='"') parclose=3;
			if(paropen&&parclose){j-=paropen; i+= parclose;}
			//Position writing heads
			str1=&(line->line[j+1]);
			str2=&(lineout[i+1]);
		}
	}
	strncpy(str1,str2,i);
}





int strncasecmp(const char *s1, const char *s2, size_t n){
	if (n == 0) return 0;
	while (n-- != 0 && tolower(*s1) == tolower(*s2)){
		if (n == 0 || *s1 == '\0' || *s2 == '\0') break;
		s1++;
		s2++;
	}
	return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
}

char * strcasestr (char *haystack, char *needle){
	char *p, *startn = 0, *np = 0;
	for(p = haystack; *p; p++){
		if(np){
			if(toupper(*p) == toupper(*np)){
				if(!*++np) return startn;
			}else np = 0;
		}else if(toupper(*p) == toupper(*needle)){
			np = needle + 1;
			startn = p;
		}
	}
	return 0;
}

void unquote(char * string){
	int i, size = (int)strlen(string)-2;
	if(string[0]=='"'){
		for(i=0;i<size;i++){
			string[i]=string[i+1];
		}
		string[i] ='\0';
	}
}

char getCharacter(int n){
	if(n>=97&&n<=122)
		return 'a'+(n-97);
	if(n>=65&&n<=90)
		return 'A'+(n-65);
	if(n>=48&&n<=57)
		return '0'+(n-48);
	switch(n){
		case 32:
			return ' ';
		case 9:
			return '\t';
		case 10:
			return '\n';
		case 13:
			return '\r';
		case 40:
			return '(';
		case 41:
			return ')';
		case 44:
			return ',';
		case 46:
			return '.';
		case 92:
			return '\\';
	}
	return '#';//code any special character
}

		





